

/**
 *
 * @author vimi Administrator
 *  Dinh Ngoc 10.08.2010
 * 
 */
import model.*;
import util.*;

import java.util.*;
import java.util.Calendar;

import java.awt.event.*;
import javax.swing.Timer;

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Category;
import org.apache.log4j.FileAppender;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.ConsoleAppender;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.PropertyConfigurator;

import org.apache.log4j.Level;

import org.apache.log4j.SimpleLayout;
import java.util.Properties;
import java.io.IOException;

import stats.CustomPlotChart;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.xy.DefaultXYDataset;

import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;

import etm.core.configuration.EtmManager;
import etm.core.monitor.EtmMonitor;
import etm.core.monitor.EtmPoint;
import etm.core.configuration.BasicEtmConfigurator;
import etm.core.renderer.SimpleTextRenderer;

import java.io.StringWriter;


public class NewRegionExplorer {
    static final Logger logger = Logger.getLogger(NewRegionExplorer.class.getName());
    // static final String LOG_PROPERTIES_FILE = "config/AppLog4J.properties";

    public InputReader _InputReader;

    public List<Course> Courses;
    private int[] Cs_sortedCs_Mapping=null;
    public List<Room> Rooms;
    private int[] Rs_sortedRs_Mapping=null;
    public int DayNum;
    public int Periods_per_Day;

    public List<Triple> _SolTriples;
    public int [][] Solution;
    public ObjectiveFunction assigned_ObjFunc;

    public int [][] bestFoundSol;
    public ObjectiveFunction assigned_bestObjFunc;

    //public
    public int TS_NCIteration = 3000;
    public int TS_NeighborNum = 50;
    
    //
    // 1. select events
    public List<Triple> StartEventCandidateList;
    

    // 2. select applicable operator
    private int [] OpIndex = {1};


    // 3. list of tabu moves
    public ArrayList<Triple> Tabu_Moves= new ArrayList<Triple>(); // <Event, <OpType, ArgValues>, ObjectiveFunction>
    public int TabuSize = 40;


    // 4. log
    private double sampleIteration= 10;
    private double sampleIterCount= 0;
    private List<XYSeries> ConstraintSerieArray = new ArrayList<XYSeries>();


    public NewRegionExplorer(FirstSolFinder _1stSolFinder)
    {
        this.Courses = _1stSolFinder.CourseDomain;
        this.Cs_sortedCs_Mapping = _1stSolFinder.Cs_sortedCs_Mapping;

        this.Rooms = _1stSolFinder.RoomDomain;
        this.Rs_sortedRs_Mapping = _1stSolFinder.Rs_sortedRs_Mapping;

        this.DayNum = _1stSolFinder._inputReader.DNum;
        this.Periods_per_Day = _1stSolFinder._inputReader.Periods_per_day;

        this._SolTriples = _1stSolFinder.L_R_P_Triples;
        this.Solution = _1stSolFinder.CP_R_Solution;
        //bestFoundSol = new int[Solution.length][Solution[0].length];
        bestFoundSol = Solution.clone();
                //new int[Solution.length][Solution[0].length];

        this._InputReader = _1stSolFinder._inputReader;

        this.assigned_ObjFunc = _1stSolFinder.assigned_ObjFunc;
        this.assigned_bestObjFunc = new ObjectiveFunction(this.assigned_ObjFunc);


        this.StartEventCandidateList = _1stSolFinder.HC4VioRelaxedCandidates;

        initializeLogger("C:/NewRegionExplorer"+this._InputReader.InputFileName+
                "_TS.log");


        // ContraintSerieArray
        for (int i=1;i< 5;i++)
        {
             XYSeries IthS;

             IthS = new XYSeries("HC"+i);

             ConstraintSerieArray.add(IthS);
        }

        for (int i=1;i< 5;i++)
        {
             XYSeries IthS;

             IthS = new XYSeries("SC"+i);

             ConstraintSerieArray.add(IthS);
        }


    }

    public void attachToRegionDigger(RegionDigger _preRegionDigger)
    {
        this._SolTriples = _preRegionDigger._SolTriples;
        this.Solution = _preRegionDigger.Solution;
        
        bestFoundSol = _preRegionDigger.bestFoundSol;
        

        this.assigned_ObjFunc = _preRegionDigger.assigned_ObjFunc;
        this.assigned_bestObjFunc = _preRegionDigger.assigned_bestObjFunc;


        this.StartEventCandidateList = _preRegionDigger.EventCandidateList;

    }

    private void initializeLogger(String filename)
    {
        PatternLayout layout = new PatternLayout("%m");

         logger.removeAllAppenders();

          FileAppender appender = null;
          try {
             appender = new FileAppender(layout,filename,false);
          } catch(Exception e) {}

        logger.addAppender(appender);
        logger.setLevel((Level) Level.DEBUG);
        logger.addAppender(new ConsoleAppender(layout));

    }

    public void run()
    {
        EtmMonitor etmMonitor = EtmManager.getEtmMonitor();
        if (etmMonitor.isStarted()) etmMonitor.reset();
        etmMonitor.start();

        EtmPoint point = etmMonitor.createPoint("New Region phase");

        Date StartTime = new Date(); // 1

        TabuSearch(TS_NCIteration);

        Date EndTime = new Date(); // 2
        long elapsed_time = EndTime.getTime() - StartTime.getTime();
        logger.info("\n  New Region phase----}} Time Measurement (ms): "+elapsed_time+"\n");


        point.collect();

        StringWriter writer = new StringWriter();
         //charttest
        SimpleTextRenderer mySimpleTextRenderer= new SimpleTextRenderer();
        etmMonitor.render(mySimpleTextRenderer);
        logger.info(writer.toString());
        etmMonitor.stop();
    }

    private void TabuSearch(int NIIteration)
    {
        int minObjFunc = assigned_bestObjFunc.value();
        int NCIteration = 0;
        int Iteration = 0;

        EtmMonitor etmMonitor = EtmManager.getEtmMonitor();
        //etmMonitor.start();
        EtmPoint IterPoint=null;
        Date StartTime= null;


        while (NCIteration<NIIteration)
        {
            Iteration++;
            if (Iteration==1)
            {
                IterPoint= etmMonitor.createPoint("New Region phase- Iteration");
                StartTime = new Date();
            }

            
            logger.info("\n");
            logger.info("TabuSearch("+NIIteration+") - ######################### Iteration "+Iteration
                                                                           + " NC"+NCIteration+"\n\n");
            logger.info("  1. StartEventCandidateList-size:"+this.StartEventCandidateList.size());

            if (this.StartEventCandidateList !=null)
            {
                logger.info("\n  EventCandidateList-Items: \n");
                for(Triple IthTriple:StartEventCandidateList)
                {
                    logger.info("                          <"+IthTriple.getFirst()+","+IthTriple.getSecond()+","+IthTriple.getThird()+"> \n");
                }
            }

            logger.info("  2. TabuMoveList-size:"+this.Tabu_Moves.size());

            if (this.Tabu_Moves !=null)
            {
                logger.info("\n  EventCandidateList-Items: < <L,R,P> , <Opt,nR,nP> , OF > \n");
                for(Triple IthTriple:this.Tabu_Moves)
                {
                    logger.info("                          < <"+((Triple)IthTriple.getFirst()).getFirst()+","+((Triple)IthTriple.getFirst()).getSecond()+","+((Triple)IthTriple.getFirst()).getThird()+"> "

                                                          +","+" <"+((Triple)IthTriple.getSecond()).getFirst()+","+((Triple)IthTriple.getSecond()).getSecond()+","+((Triple)IthTriple.getSecond()).getThird()+"> "

                                                          +"," +IthTriple.getThird()+"> \n");
                }
            }
            

            Triple move =  selectMove(generateNeighborMoves(TS_NeighborNum),assigned_ObjFunc.value());
            //Triple move =  selectMove(generateNeighborMoves(TS_NeighborNum),assigned_bestObjFunc.value());
            if (move != null)
            {
                doMove(move);

                
                logger.info("\n doMove:"+"\n");
                //Interation = 0;

                Triple _Event = (Triple) move.getFirst();

                    logger.info("Event:"+_Event.getFirst()+","
                                                +_Event.getSecond()+","+
                                                 _Event.getThird()+"\n");
                

                Triple _part2 = (Triple) move.getSecond();

                logger.info(" -- Opt, newRoom, newTimeslot:"+_part2.getFirst()+","
                                                +_part2.getSecond()+","+
                                                 _part2.getThird()+"\n");

                logger.info(" -- OF:"+move.getThird()+"\n");
                


                printPenalties(this.Solution,assigned_ObjFunc);

            }

            int afterObjFunc = assigned_ObjFunc.value();

            
            logger.info("     afterObjFunc: "+afterObjFunc+" "+this.assigned_ObjFunc.HC1+"+"+
                                this.assigned_ObjFunc.HC2+"+"+
                                this.assigned_ObjFunc.HC3+"+"+
                                this.assigned_ObjFunc.HC4+" + "+
                                this.assigned_ObjFunc.SC1+"+"+
                                this.assigned_ObjFunc.SC2+"+"+
                                this.assigned_ObjFunc.SC3+"+"+
                                this.assigned_ObjFunc.SC4+"=>"+
                                this.assigned_ObjFunc.value()+"\n"
                                );

            logger.info("     minObjFunc "+minObjFunc+" "+this.assigned_bestObjFunc.HC1+"+"+
                                this.assigned_bestObjFunc.HC2+"+"+
                                this.assigned_bestObjFunc.HC3+"+"+
                                this.assigned_bestObjFunc.HC4+" + "+
                                this.assigned_bestObjFunc.SC1+"+"+
                                this.assigned_bestObjFunc.SC2+"+"+
                                this.assigned_bestObjFunc.SC3+"+"+
                                this.assigned_bestObjFunc.SC4+"=>"+
                                this.assigned_bestObjFunc.value()+"\n"
                                );
             
           logger.info(this.assigned_ObjFunc.value()+"\n");

            if (afterObjFunc>=minObjFunc) NCIteration++;
            else
            {
                minObjFunc = afterObjFunc;
                NCIteration =0;

                bestFoundSol = Solution.clone();

                assigned_bestObjFunc.copyFrom( assigned_ObjFunc) ;

            }


            if (Iteration==1)
            {
                Date EndTime = new Date(); // 2
                long elapsed_time = EndTime.getTime() - StartTime.getTime();
                logger.info("\n  Iteration New Region phase----}} Time Measurement (ms): "+elapsed_time+"\n");
                IterPoint.collect();
            }


            // log convergence
            if (sampleIterCount==sampleIteration)
            {
               this.sampleIterCount=0;

               /*
               for (int i=0;i< ConstraintSerieArray.size();i++)
                {
                    ConstraintSerieArray.get(i).add(NCIteration, assigned_ObjFunc.value());
                }
                *
                */

               ConstraintSerieArray.get(0).add(Iteration, assigned_ObjFunc.HC1);
               ConstraintSerieArray.get(1).add(Iteration, assigned_ObjFunc.HC2);
               ConstraintSerieArray.get(2).add(Iteration, assigned_ObjFunc.HC3);
               ConstraintSerieArray.get(3).add(Iteration, assigned_ObjFunc.HC4);

               ConstraintSerieArray.get(4).add(Iteration, assigned_ObjFunc.SC1);
               ConstraintSerieArray.get(5).add(Iteration, assigned_ObjFunc.SC2);
               ConstraintSerieArray.get(6).add(Iteration, assigned_ObjFunc.SC3);
               ConstraintSerieArray.get(7).add(Iteration, assigned_ObjFunc.SC4);

            }else sampleIterCount++;


        }


    }




    private Triple selectMove(List<Triple> _NeighborMoves, int OF)
    {
         Triple move = _NeighborMoves.get(0);
         int moveOF = Integer.parseInt(move.getThird().toString());

         

         if (OF>-1)
         {
           if (moveOF<=OF) return move;
         }else if (move!=null) return move;

         return null;
    }



    private void doMove(Triple move)
    {
        Object Part1=move.getFirst();

        Triple Part2= (Triple) move.getSecond();
        int OptType = Integer.parseInt(Part2.getFirst().toString());
        int newRoom = Integer.parseInt(Part2.getSecond().toString());
        int newTimeslot = Integer.parseInt(Part2.getThird().toString());

        int OF_Part3 = Integer.parseInt(move.getThird().toString());


        Triple Event = (Triple) Part1;

        if (OptType==1) ChangeRoomTime(Event,newRoom,newTimeslot,true);


        if (this.Tabu_Moves.size()== this.TabuSize)
        {
            this.Tabu_Moves.remove(TabuSize-1);
            this.Tabu_Moves.add(0,move);

        } else this.Tabu_Moves.add(0,move);

    }



    public List<Triple> generateNeighborMoves(int Num)
    {
        List<Triple> retMoves = new ArrayList<Triple>();



        for (int i=0;i<Num;i++)
        {
            Triple IthMove = generateMove();

            if (!retMoves.contains(IthMove) && !testContainTBList(Tabu_Moves, IthMove))
            {
                int insertPos=0;
                for (Triple move:retMoves)
                {
                    int IthOF= Integer.parseInt(IthMove.getThird().toString());
                    int moveOF= Integer.parseInt(move.getThird().toString());
                    if (IthOF<=moveOF) break;
                    insertPos++;
                }
                retMoves.add(insertPos,IthMove);
            }else i--;

        }




        return retMoves; // sorted
    }


    public Triple generateMove()
    {
        // logger.info("generateMove");

        // 1. Select Event
        Triple selectedEvent= null;

        // 20% - 80%
        while (selectedEvent == null)
        {
            if (Math.random()<0.4)
            {
                selectedEvent = _SolTriples.get(RandomUtil.retRandNum(_SolTriples.size()-1));
            }else
            {
                if (!StartEventCandidateList.isEmpty())
                {
                selectedEvent = StartEventCandidateList.get(0);
                }
            }
        }


        // 2.1. Select Opt
        int OptTyp = 1; // OpIndex[RandomUtil.retRandNum(2)];
        
        /*
        double randNum = Math.random();


        if (randNum<=0.3333333333) OptTyp = 1;
        else
        {
            if (randNum>0.6666666666) OptTyp = 3;
            else OptTyp = 2;
        }
         
         */


        //logger.info("OptTyp: "+OptTyp);


        // 2.2. chooseArgValues for chosen Opt
        // a.
        int c = Integer.parseInt(selectedEvent.getFirst().toString());
        int [] TabuPeriods = new int[Courses.get(c).getLectureNum()];
        int lastP = 0;
        for (int j=0;j<Solution[c].length;j++)
        {

                if (Solution[c][j]>-1)
                {
                    // int r = Solution[c][j];
                    TabuPeriods[lastP] = j;
                    if (lastP<TabuPeriods.length-1) lastP++;
                }
        }

        int newTimeSlot=0;


        // b.
        // int [] TabuRooms;
        int newRoom=0;

        boolean HC2Violated = true;
        int HC2ViolatedLoop = 0;
        while (HC2Violated && HC2ViolatedLoop<300)
        {

            newTimeSlot = RandomUtil.retRandNum(Solution[0].length-1,TabuPeriods);
            newRoom = RandomUtil.retRandNum(Rooms.size()-1,Integer.parseInt(selectedEvent.getSecond().toString()));

            HC2Violated = testHC2Violation(c,newRoom, newTimeSlot,this.Solution);
            HC2ViolatedLoop++;
        }

        

        // 3. precalc ObjectiveFunction
        int [][] _tempSolution = null;


        if (OptTyp ==1)
        {
            _tempSolution=ChangeRoomTime(selectedEvent, newRoom, newTimeSlot, false);
        }

      

        int preHCValue = this.assigned_ObjFunc.valueHCwW();

        printPenalties(_tempSolution, this.assigned_ObjFunc);

        // Move violate more HardConstraint muss be reviewed
        /*
        if (this.StartEventCandidateList.size()<100)
        {
          if (this.assigned_ObjFunc.valueHCwW()>preHCValue+10)
          {
              if (!testContain((ArrayList) StartEventCandidateList,selectedEvent)) this.StartEventCandidateList.add(selectedEvent);
          }
        }
        */
        


        int ObjectiveFunc = this.assigned_ObjFunc.value();

        // 4. build data parts of Triple
        Object Part1 = selectedEvent;
        Triple Part2= new Triple(OptTyp,newRoom,newTimeSlot);

        int Part3 = ObjectiveFunc;

        return new Triple(Part1,Part2,Part3);
    }

    private boolean testContain(ArrayList<Triple> _EventCandidateList, Triple _selectedEvent)
    {

        for(int i=0;i<_EventCandidateList.size();i++)
        {
            Triple IthEvent = _EventCandidateList.get(i);
            if (IthEvent.getFirst().toString().equals(_selectedEvent.getFirst().toString())
                && IthEvent.getSecond().toString().equals(_selectedEvent.getSecond().toString())
                && IthEvent.getThird().toString().equals(_selectedEvent.getThird().toString())
               ) return true;
        }

        return false;
    }


    private boolean testContainTBList(ArrayList<Triple> _TabuMovesList, Triple _selectedMove)
    {
        
        for(int i=0;i<_TabuMovesList.size();i++)
        {
            boolean EventSame=false;
            boolean Opt_R_T_Same = false;
            boolean OF_same = false;

            Triple IthEvent = (Triple) _TabuMovesList.get(i).getFirst();
            if (IthEvent.getFirst().toString().equals(((Triple)_selectedMove.getFirst()).getFirst().toString())
                && IthEvent.getSecond().toString().equals(((Triple) _selectedMove.getFirst()).getSecond().toString())
                && IthEvent.getThird().toString().equals(((Triple)_selectedMove.getFirst()).getThird().toString())
               ) EventSame = true;


            Triple Opt_Room_Time = (Triple) _TabuMovesList.get(i).getSecond();

            if (Opt_Room_Time.getFirst().toString().equals(((Triple)_selectedMove.getSecond()).getFirst().toString())
                && Opt_Room_Time.getSecond().toString().equals(((Triple) _selectedMove.getSecond()).getSecond().toString())
                && Opt_Room_Time.getThird().toString().equals(((Triple)_selectedMove.getSecond()).getThird().toString())
               ) Opt_R_T_Same = true;

            int _selectedMoveOF = Integer.parseInt( _selectedMove.getThird().toString());
            if (_selectedMoveOF == Integer.parseInt( _TabuMovesList.get(i).getThird().toString()))
                    OF_same = true;


            if (EventSame && Opt_R_T_Same && OF_same) return true;

        }

        return false;
    }


    private boolean testHC2Violation(int _c,int _Room, int _TimeSlot, int [][] _Solution)
    {
        for (int c=0;c<_Solution.length;c++)
        {
            if (c != _c && _Solution[c][_TimeSlot]==_Room)
            {
                return true;
            }
        }

        return false;
    }

    private void printPenalties(int [][] _sol, ObjectiveFunction _ObFunc)
    {
        PernaltyCounter _PenaltyCounter = new PernaltyCounter();
        this.attachTo(_PenaltyCounter);
        _PenaltyCounter.CP_R_Solution = _sol;

        if (_ObFunc==null)
        {
            _ObFunc = new ObjectiveFunction();
        }

        _ObFunc.assigned_Solution = _sol;

        _ObFunc.HC1 = _PenaltyCounter.AllLecturesOnTT();
        _ObFunc.HC2 = _PenaltyCounter.RoomOccupancy();
        _ObFunc.HC3 = _PenaltyCounter.sameCurriculumLecturesConflict(_InputReader.HardCurriculum_Matrix, this.Cs_sortedCs_Mapping)
                         +_PenaltyCounter.sameTeacherLecturesConflict(_InputReader.Courses_waTeacher_Matrix, this.Cs_sortedCs_Mapping);
        _ObFunc.HC4 = _PenaltyCounter.TeacherAvailabilities(_InputReader.C_P_UnavailabilityMatrix, this.Cs_sortedCs_Mapping);

         _ObFunc.SC1 = _PenaltyCounter.RoomCapacity();
         _ObFunc.SC2 = _PenaltyCounter.MinimumWorkingDays(_InputReader.Periods_per_day);
         _ObFunc.SC3 = _PenaltyCounter.CurriculumCompactness();
         _ObFunc.SC4 = _PenaltyCounter.RoomStability();


    }

    public void attachTo(PernaltyCounter _pc)
    {
        _pc.CourseDomain = this.Courses;
        _pc.Curricula = this._InputReader.Curricula;
        _pc.DayNum = this.DayNum;
        _pc.periods_per_day = this.Periods_per_Day;

        _pc.RoomDomain = this.Rooms;
        _pc.CP_R_Solution = this.Solution;




    }


    // Operator

    private int [][] ChangeRoomTime(Triple lecture,int newRoom, int newTimeSlot,boolean notTest)
    {
       int [][] _tempSolution = new int[this.Solution.length][this.Solution[0].length];



        for (int i=0;i<_tempSolution.length;i++)
        {
            for (int j=0;j<_tempSolution[i].length;j++)
            {
                _tempSolution[i][j]= Solution[i][j];
            }
        }

       int c= Integer.parseInt(lecture.getFirst().toString());
       int r= Integer.parseInt(lecture.getSecond().toString());
       int p= Integer.parseInt(lecture.getThird().toString());

       _tempSolution[c][p] =-1;
       _tempSolution[c][newTimeSlot] =newRoom;

       if (notTest)
       {
           Solution[c][p] =-1;
           Solution[c][newTimeSlot] =newRoom;

           lecture.setSecond(newRoom);
           lecture.setThird(newTimeSlot);
           //if (notTest) logger.info("ChangeRoomTime");
       }

      

        return _tempSolution;
    }


    public void writeSolDown()
    {
        SolWriter _solWriter = new SolWriter("C:/NewRegionExplorer"+this._InputReader.InputFileName+
                "_TS.sol");

        // Calendar.getInstance().getTime()
        _solWriter.Courses = this.Courses;
        _solWriter.Rooms = this.Rooms;
        _solWriter.Solution = this.bestFoundSol;

        _solWriter.DayNum = this.DayNum;
        _solWriter.Periods_per_Day = this.Periods_per_Day;

        _solWriter.writeSolDown();

    }


    protected void finalize()
    {
        writeSolDown();
    }


    public void showBestSolinChart()
    {

        // A scatter plot displays data from an XYDataset.
        

        // create a dataset...
        List<XYSeries> SerieArray = new ArrayList<XYSeries>();

         for (int i=0;i< this.Courses.size();i++)
         {
             XYSeries IthS = new XYSeries(Courses.get(i).getCourseID());

             SerieArray.add(IthS);
         }


        for (int i=0;i< this.bestFoundSol.length;i++)
        {
            //System.out.print(myInputReader.Courses.get(i).getCourseID()+": ");

            for (int j=0;j< this.bestFoundSol[i].length;j++)
            {
                //System.out.print(myInputReader.HardCurriculum_Matrix[i][j]+" ");
                if (this.bestFoundSol[i][j]>-1) SerieArray.get(i).add(j, this.bestFoundSol[i][j]);
            }

        }




        XYSeriesCollection dataset = new XYSeriesCollection();

        for (int i=0;i< SerieArray.size();i++)
         {
             XYSeries IthS = SerieArray.get(i);

             dataset.addSeries(IthS);
         }

        // create a chart...

        CustomPlotChart chartFrame = new CustomPlotChart("Phase NewRegionExplorer - Solution "+this._InputReader.InputFileName,"Period("+_InputReader.DNum+"x"+_InputReader.Periods_per_day+")"
                   +"         OF:"+this.assigned_bestObjFunc.HC1+"+"+
                                this.assigned_bestObjFunc.HC2+"+"+
                                this.assigned_bestObjFunc.HC3+"+"+
                                this.assigned_bestObjFunc.HC4+" + "+
                                this.assigned_bestObjFunc.SC1+"+"+
                                this.assigned_bestObjFunc.SC2+"+"+
                                this.assigned_bestObjFunc.SC3+"+"+
                                this.assigned_bestObjFunc.SC4+"=>"+
                                this.assigned_bestObjFunc.value(),"Room",dataset,"C:/NewRegionExplorer"+this._InputReader.InputFileName+ "_TS.png");
        

        chartFrame.setChartText(this.assigned_bestObjFunc.HC1+"+"+
                                this.assigned_bestObjFunc.HC2+"+"+
                                this.assigned_bestObjFunc.HC3+"+"+
                                this.assigned_bestObjFunc.HC4+" + "+
                                this.assigned_bestObjFunc.SC1+"+"+
                                this.assigned_bestObjFunc.SC2+"+"+
                                this.assigned_bestObjFunc.SC3+"+"+
                                this.assigned_bestObjFunc.SC4+"=>"+
                                this.assigned_bestObjFunc.value()
                                );


	chartFrame.pack();
	chartFrame.setVisible(true);



    }


    public void showConvergenceinChart()
    {

        // A scatter plot displays data from an XYDataset.

        // create a dataset...



        XYSeriesCollection dataset = new XYSeriesCollection();

        for (int i=0;i< ConstraintSerieArray.size();i++)
         {
             XYSeries IthS = ConstraintSerieArray.get(i);

             dataset.addSeries(IthS);
         }

        // create a chart...

        CustomPlotChart chartFrame = new CustomPlotChart("Phase NewRegionExplorer - Convergence "+this._InputReader.InputFileName,"Iteration","Violation",dataset,"C:/NewRegionExplorer"+this._InputReader.InputFileName+"_TSConvergence.png");


	chartFrame.pack();
	chartFrame.setVisible(true);



    }

}
